-- Combat Engine 1.0

g_skill = {}

function Msg(outstr,a1,a2,a3)
	DEFAULT_CHAT_FRAME:AddMessage(tostring(outstr),a1,a2,a3)
end

function RogueScoutFull(arg1, arg2)
    local Skill = {}
    local i = 0
    local energy = UnitMana("player")
    local focus = UnitSkill("player")
    local friendly = (not UnitCanAttack("player", "target"))
    local combat = GetPlayerCombatState()
    local tspell,ttime,telapsed = UnitCastingTime("target")
    local pbuffs = BuffList("player")
    local tbuffs = BuffList("target")

    i=i+1; Skill[i] = { name = "Throat Attack",  use = ((not friendly) and (tspell ~= nil) and (ttime >= 1) and ((ttime - telapsed) > 0.5) and (focus >= 15)) }
    i=i+1; Skill[i] = { name = "Combat Master",  use = ((not string.find(pbuffs, "Combat Master")) and (not string.find(pbuffs, "Informer"))) }
    i=i+1; Skill[i] = { name = "Sneak Attack",   use = ((not friendly) and (energy >= 30) and (arg2 == "behind") and (not combat)) }
    i=i+1; Skill[i] = { name = "Blind Spot",     use = ((not friendly) and (energy >= 25) and (not string.find(tbuffs, "Bleed")) and (arg2 == "behind")) }
    i=i+1; Skill[i] = { name = "Shadowstab",     use = ((not friendly) and (energy >= 35) and (not string.find(tbuffs, "Bleed"))) }
    i=i+1; Skill[i] = { name = "Wound Attack",   use = ((not friendly) and (energy >= 35) and string.find(tbuffs, "Bleed") and string.find(tbuffs, "Grievous Wound")) }
    i=i+1; Skill[i] = { name = "Low Blow",       use = ((not friendly) and (energy >= 35) and string.find(tbuffs, "Bleed")) }
    i=i+1; Skill[i] = { name = "Vampire Arrows", use = (not friendly) }
    i=i+1; Skill[i] = { name = "Shot",           use = (not friendly) }
    
    MyCombat(Skill,arg1)
end

function RogueScout(arg1, arg2)
    local Skill = {}
    local i = 0
    local energy = UnitMana("player")
    local focus = UnitSkill("player")
    local friendly = (not UnitCanAttack("player", "target"))
    local combat = GetPlayerCombatState()
    local tspell,ttime,telapsed = UnitCastingTime("target")
    local pbuffs = BuffList("player")
    local tbuffs = BuffList("target")

    --i=i+1; Skill[i] = { name = "Combat Master",  use = ((not string.find(pbuffs, "Combat Master")) and (not string.find(pbuffs, "Informer"))) }
    --i=i+1; Skill[i] = { name = "Sneak Attack",   use = ((not friendly) and (energy >= 30) and (arg2 == "behind") and (not combat)) }
    --i=i+1; Skill[i] = { name = "Blind Spot",     use = ((not friendly) and (energy >= 25) and (not string.find(tbuffs, "Bleed")) and (arg2 == "behind")) }
    i=i+1; Skill[i] = { name = "Shadowstab",     use = ((not friendly) and (energy >= 20) and (not string.find(tbuffs, "Bleed"))) }
    i=i+1; Skill[i] = { name = "Wound Attack",   use = ((not friendly) and (energy >= 35) and string.find(tbuffs, "Bleed") and string.find(tbuffs, "Grievous Wound")) }
    i=i+1; Skill[i] = { name = "Low Blow",       use = ((not friendly) and (energy >= 35) and string.find(tbuffs, "Bleed")) }
    --i=i+1; Skill[i] = { name = "Vampire Arrows", use = (not friendly) }
    --i=i+1; Skill[i] = { name = "Shot",           use = (not friendly) }
    
    MyCombat(Skill,arg1)
end

function PriestKnight(arg1)
    local Skill = {}
    local i = 0
    local friendly = (not UnitCanAttack("player", "target"))
    local combat = GetPlayerCombatState()
    local pbuffs = BuffList("player")
    local tbuffs = BuffList("target")
    local health, buffs
	
	
    if friendly then
        health = PctH("target")
        buffs = tbuffs
    else
        health = PctH("player")
        buffs = pbuffs
    end
	
    i=i+1; Skill[i] = { name = "Magic Barrier",         use = ((not combat) and (not string.find(pbuffs, "Magic Barrier"))) }
    i=i+1; Skill[i] = { name = "Blessed Spring Water",  use = ((not combat) and (not string.find(pbuffs, "Blessed Spring Water"))) }
    i=i+1; Skill[i] = { name = "Soul Bond",             use = (not string.find(pbuffs, "Soul Bond")) }
    i=i+1; Skill[i] = { name = "Soul Source",           use = (health <= .25) }
    i=i+1; Skill[i] = { name = "Holy Aura",             use = (PctH("player") <= .40) }
    i=i+1; Skill[i] = { name = "Heal",                  use = (health <= .50) }
    i=i+1; Skill[i] = { name = "Urgent Heal",           use = (health <= .80) }
    i=i+1; Skill[i] = { name = "Regenerate",            use = ((health <= .95) and (not string.find(buffs, "Regenerate"))) }
    i=i+1; Skill[i] = { name = "Grace of Life",         use = (not string.find(pbuffs, "Grace of Life")) }
    i=i+1; Skill[i] = { name = "Amplified Attack",      use = (friendly and (not string.find(tbuffs, "Amplified Attack"))) }
    i=i+1; Skill[i] = { name = "Enhanced Armor",        use = (not string.find(pbuffs, "Enhanced Armor")) }
    i=i+1; Skill[i] = { name = "Bone Chill",            use = ((not friendly) and (not string.find(tbuffs, "Bone Chill"))) }
    i=i+1; Skill[i] = { name = "Rising Tide",           use = (not friendly) }

    MyCombat(Skill,arg1)
end

function KnightPriest(arg1, arg2)
    local Skill = {}
    local i = 0
    local friendly = (not UnitCanAttack("player", "target"))
    local shield = (GetEquipSlotInfo(17) ~= nil)
    local combat = GetPlayerCombatState()
	local manareturncd = CD("Mana Return")
	
    local pbuffs = BuffList("player")
    local tbuffs = BuffList("target")
	local health, buffs
	
    if friendly then
        health = PctH("target")
        buffs = tbuffs
    else
        health = PctH("player")
        buffs = pbuffs
    end

    --i=i+1; Skill[i] = { name = "Whirlwind Shield",     use = ((not friendly) and shield) }
    i=i+1; Skill[i] = { name = "Urgent Heal",          use = (health <= .50) }
	i=i+1; Skill[i] = { name = "Regenerate",           use = ((health <= .75) and (not string.find(buffs, "Regenerate"))) }
	i=i+1; Skill[i] = { name = "Enhanced Armor",       use = (not string.find(pbuffs, "Enhanced Armor")) }
    i=i+1; Skill[i] = { name = "Holy Seal",            use = (not string.find(pbuffs, "Holy Seal")) }
    i=i+1; Skill[i] = { name = "Threaten",             use = (string.find(tbuffs, "Holy Seals 3") and (not string.find(pbuffs, "Threaten")) and (arg2 == "threaten")) }
    i=i+1; Skill[i] = { name = "Mana Return",          use = (string.find(tbuffs, "Holy Seals 3")) }
    i=i+1; Skill[i] = { name = "Punishment",           use = ((not friendly) and string.find(tbuffs, "Light Seal III") and (not manareturncd)) }
    i=i+1; Skill[i] = { name = "Holy Strike",          use = (not friendly) }

    MyCombat(Skill,arg1)
end

function ReadSkills()
	g_skill = {}
	local skillname,slot

	Msg("- Reading Class Skills")
	for page = 1,4 do
		slot = 1
		skillname = GetSkillDetail(page,slot)
		repeat
			local a1,a2,a3,a4,a5,a6,a7,a8,skillusable = GetSkillDetail(page,slot)
			if skillusable then
				g_skill[skillname] = { ["page"] = page, ["slot"] = slot }
			end
			slot = slot + 1
			skillname = GetSkillDetail(page,slot)
		until skillname == nil
	end
end
ReadSkills() -- Read skills into g_skill table at login

function PctH(tgt)
	return (UnitHealth(tgt)/UnitMaxHealth(tgt))
end

function PctM(tgt)
	return (UnitMana(tgt)/UnitMaxMana(tgt))
end

function PctS(tgt)
	return (UnitSkill(tgt)/UnitMaxSkill(tgt))
end

function CancelBuff(buffname)
	local i = 1
	local buff = UnitBuff("player",i)

	while buff ~= nil do
		if buff == buffname then
			CancelPlayerBuff(i)
			return true
		end

		i = i + 1
		buff = UnitBuff("player",i)
	end
	return false
end

function BuffTimeLeft(tgt, buffname)
    local cnt = 1
    local buffcmd, bufftimecmd, buff

    if UnitCanAttack("player", tgt) then
        buffcmd = UnitDebuff
        bufftimecmd = UnitDebuffLeftTime
    else
        buffcmd = UnitBuff
        bufftimecmd = UnitBuffLeftTime
    end

    buff = buffcmd(tgt, cnt)

    while buff ~= nil do
        if string.find(buff, buffname) then
            return bufftimecmd(tgt, cnt)
        end
        cnt = cnt + 1
        buff = buffcmd(tgt, cnt)
    end

    return 0
end

function ChkBuff(tgt,buffname)
	local cnt = 1
	local buffcmd = UnitBuff

	if UnitCanAttack("player",tgt) then
		buffcmd = UnitDebuff
	end
	local buff = buffcmd(tgt,cnt)

	while buff ~= nil do
		if string.gsub(buff, "(%()(.)(%))", "%2") == buffname then
			return true
		end
		cnt = cnt + 1
		buff = buffcmd(tgt,cnt)
	end
	return false
end

function BuffList(tgt)
    local cnt = 1
    local buffcmd = UnitBuff
    local buffstr = "/"

    if UnitCanAttack("player",tgt) then
        buffcmd = UnitDebuff
    end
    local buff = buffcmd(tgt,cnt)

    while buff ~= nil do
        buffstr = buffstr..buff.."/"
        cnt = cnt + 1
        buff = buffcmd(tgt,cnt)
    end

    return string.gsub(buffstr, "(%()(.)(%))", "%2")
end

function CD(skillname)
	local firstskill = GetSkillDetail(2,1)
	if (g_skill[firstskill] == nil) or (g_skill[firstskill].page ~= 2) then
		ReadSkills()
	end

	if g_skill[skillname] ~= nil then
		local tt,cd = GetSkillCooldown(g_skill[skillname].page,g_skill[skillname].slot)
		return cd==0
	elseif skillname == nil then
		return false
	else
		Msg("Skill not available: "..skillname)
		return false
	end
end

function MyCombat(Skill, arg1)
	local spell_name = UnitCastingTime("player")
	local talktome = ((arg1 == "v1") or (arg1 == "v2"))
	local action,actioncd,actiondef,actioncnt
	
	if spell_name ~= nil then
		if (arg1 == "v2") then Msg("- ["..spell_name.."]", 0, 1, 1) end
		return true
	end

	for x,tbl in ipairs(Skill) do
		if Skill[x].use then
			if string.find(Skill[x].name, "Action:") then
				action = tonumber((string.gsub(Skill[x].name, "(Action:)( *)(%d+)(.*)", "%3")))
				_1,actioncd = GetActionCooldown(action)
				actiondef,_1,actioncnt = GetActionInfo(action)
				if GetActionUsable(action) and (actioncd == 0) and (actiondef ~= nil) and (actioncnt > 0) then
					if talktome then Msg("- "..Skill[x].name) end
					UseAction(action)
					return true
				end
			elseif string.find(Skill[x].name, "Custom:") then
				action = string.gsub(Skill[x].name, "(Custom:)( *)(.*)", "%3")
				if CustomAction(action) then
					return true
				end
			elseif string.find(Skill[x].name, "Item:") then
				action = string.gsub(Skill[x].name, "(Item:)( *)(.*)", "%3")
				if talktome then Msg("- "..Skill[x].name) end
				UseItemByName(action)
				return true
			elseif CD(Skill[x].name) then
				if talktome then Msg("- "..Skill[x].name) end
				CastSpellByName(Skill[x].name)
				return true
			end
		end
	end
	if (arg1 == "v2") then Msg("- [IDLE]", 0, 1, 1) end

	return false
end
